package cn.gov.mwr.szy206;

import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
 




import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;

import cn.gov.mwr.szy206.body.BodyUp;
import cn.gov.mwr.szy206.data.BaseData;
import cn.gov.mwr.szy206.data.Data1B;
import cn.gov.mwr.szy206.data.Data1F;
import cn.gov.mwr.szy206.data.Data50;
import cn.gov.mwr.szy206.data.Data51;
import cn.gov.mwr.szy206.data.Data52;
import cn.gov.mwr.szy206.data.Data54;
import cn.gov.mwr.szy206.data.Data53;
import cn.gov.mwr.szy206.data.Data55;
import cn.gov.mwr.szy206.data.Data56;
import cn.gov.mwr.szy206.data.Data57;
import cn.gov.mwr.szy206.data.Data57Item;
import cn.gov.mwr.szy206.data.Data58;
import cn.gov.mwr.szy206.data.Data58Item;
import cn.gov.mwr.szy206.data.Data59;
import cn.gov.mwr.szy206.data.DataC0;
import cn.gov.mwr.szy206.data.DataC0D1;
import cn.gov.mwr.szy206.data.IData;
import cn.gov.mwr.szy206.utils.ByteUtil;
import cn.gov.mwr.szy206.utils.CrcUtil;

/**
 * 水资源解析类，主要为水资源协议接收到的信息做整体解析
 * 
 * @ClassName: SzyParser
 * @Description: 水资源解析类,主要针对水资源协议接收到的信息做整体解析，其中包括了对测站编码、地址、时钟、控制位、CRC校验，TPDelay,TpTime以及每个报文项的解析
 * @author lipujun
 * @date Jun 6, 2013
 * 
 */
public class SzyParser {

	/**
	 * 获取控制域C
	 * 
	 * @param C
	 * @return DIR, DIV, FCB, FUNC
	 *         ------------------------------------------------------------
	 *         获取传输方向位DIR
	 * 
	 *         1) DIR=0，表示此帧报文是由中心站发出的下行报文；
	 * 
	 *         2) DIR=1，表示此帧报文是由终端发出的上行报文；
	 * 
	 *         ------------------------------------------------------------
	 *         获取报文的帧数DIV，0为单帧；1为多帧
	 * 
	 *         1) DIV =1，表示此报文已被拆分为若干帧，接收后需要拼接。
	 * 
	 *         此时控制域C 后增加一个字节，为拆分帧计数DIVS，采用BIN 倒计数（255～1），1 时表示最后一帧。
	 * 
	 *         启动站发送时自动加上发送，从动站返回帧时对应加上确认；
	 * 
	 *         2) DIV =0，表示此帧报文为单帧。
	 * 
	 *         ---------------------------------------------------------------
	 *         1) FCB 表示每个站连续的发送/确认或者请求/响应的变化位。
	 * 
	 *         FCB 位用来防止信息传输的丢失和重复；
	 * 
	 *         2) 启动站向同一从动站传输新的发送/确认或请求/响应传输时，启动站将设置FCB 值，若超
	 *         时未收到从动站的报文，或接收出现差错，则启动站将FCB 减1，重复原来的发送/确认 或者请求/响应，直到FCB
	 *         值为0，表示本次传输服务失败；
	 * 
	 *         3) 从动站收到启动站FCB 值不为0 的报文并按照要求确认或响应时，返回相应的FCB 值。
	 * 
	 *         ---------------------------------------------------------------
	 *         /** 获取功能码，需根据上下行的标识来判定功能码
	 * 
	 *         0 确认认可
	 * 
	 *         1 ：雨量参数 ,2： 水位参数
	 * 
	 *         3： 流量（水量）参数, 4 ：流速参数
	 * 
	 *         5： 闸位参数,6： 功率参数
	 * 
	 *         7 ：气压参数,8 ：风速参数
	 * 
	 *         9 ：水温参数,10： 水质参数
	 * 
	 *         11： 土壤含水率参数,12： 蒸发量参数
	 * 
	 *         13： 报警或状态参数,14： 统计雨量
	 * 
	 *         15： 水压参数
	 * 
	 */
	public static int[] parseControl(byte C) {

		String binstr = ByteUtil.toBinaryString(C);

		// String DIR = binstr.substring(0, 1);
		// String DIV = binstr.substring(1, 2);
		// String FCB = binstr.substring(2, 4);
		// String FUNC = binstr.substring(4, 8);
		byte DIR = (byte) ((C & 0x80) >> 7);
		byte DIV = (byte) ((C & 0x40) >> 6);
		byte FCB = (byte) ((C & 0x30) >> 4);
		byte FUNC = (byte) (C & 0x0F);

		// System.out.println(">> binstr " + binstr + " DIR " + DIR + " DIV "
		// + DIV + " FCB " + FCB + " FUNC " + FUNC);

		return new int[] { DIR, DIV, FCB, FUNC };
	}

	/**
	 * 解析遥测站地址
	 * 
	 * @param data
	 * @return
	 */
	public static String parseStcd(byte[] data) {
		String stcd = "";

		if (data != null && data.length == 5) {

			if (data[0] == 0x00) {
				// 按《SL 502》标准协议
				// System.out.println("stcd sl502");
				stcd = ByteUtil.bcd2Str(new byte[] { data[1], data[2], data[3],
						data[4] });

			} else {
				// 前三个字节A5、A4、A3采用GB2260—2007规定的行政区划代码的前6位，
				// System.out.println("stcd GB2260—2007");
				stcd = ByteUtil
						.bcd2Str(new byte[] { data[0], data[1], data[2] });

				// 后两个字节A2、A1为遥测站地址自定义段，采用HEX码，中心站解码时还原为3个字节BCD码；
				// 遥测站地址自定义1～60000,中继站地址自定义60001～65534
				int addr = ByteUtil
						.bytesToShort(new byte[] { data[4], data[3] });

				// 因为考虑到地址小于10000的现象，则需要左补0，3字节，总共为6位
				String addrStr = StringUtils.leftPad(String.valueOf(addr), 6,
						"0");// 6为三字节最大位数，在左补0

				stcd = stcd + addrStr;
			}
		}

		return stcd;
	}

	/**
	 * 获取地址域A
	 * 
	 * 解析遥测站地址，参见协议5.1.4.3
	 * 
	 * 参考水文协议中的解析遥测站地址的方法，参见6.2.3.2
	 * 
	 * @param stcd
	 */
	public static String parseAddress(byte[] data) {
		String stcd = "";

		if (data != null && data.length == 5) {

			if (data[0] == 0x00) {
				// 按《SL 502》标准协议
				stcd = ByteUtil.bcd2Str(new byte[] { data[1], data[2], data[3],
						data[4] });

			} else {
				// 前三个字节A5、A4、A3采用GB2260—2007规定的行政区划代码的前6位，
				stcd = ByteUtil
						.bcd2Str(new byte[] { data[0], data[1], data[2] });

				// 后两个字节A2、A1为遥测站地址自定义段，采用HEX码，中心站解码时还原为3个字节BCD码；
				// 遥测站地址自定义1～60000,中继站地址自定义60001～65534
				int addr = ByteUtil
						.bytesToUshort(new byte[] { data[4], data[3] });

				// 因为考虑到地址小于10000的现象，则需要左补0，3字节，总共为6位
				String addrStr = StringUtils.leftPad(String.valueOf(addr), 6,
						"0");// 6为三字节最大位数，在左补0

				stcd = stcd + addrStr;
			}
		}

		return stcd;
	}

	/**
	 * 返回值：年月日时分秒，星期数
	 * 
	 * 应用场景：
	 * 
	 * 1、设置遥测终端或中继站时钟（AFN=11H）
	 * 
	 * 2、查询遥测终端或中继站时钟（AFN=51H）
	 * 
	 * 
	 */
	public static String parseClock(byte[] data) {

		ArrayUtils.reverse(data);
		byte week = (byte) (data[1] >> 5);
		byte d4low = (byte) (data[1] & 0x1F);
		String datestr = ByteUtil.bcd2Str(new byte[] { data[0], d4low,
				data[2], data[3], data[4], data[5] });

		System.out.println(">> 当前时间：" + datestr + " 星期 " + week);
		return datestr;
		// SimpleDateFormat sdf = new SimpleDateFormat("yyMMddHHmmss");//

		// Date curDate = new Date(System.currentTimeMillis());

	}

	/**
	 * 解析数据长度
	 * 
	 * @param datalen
	 * @return
	 */
	public static int parseDataLen(byte[] datalen) {
		if (datalen.length == 1) {
			return ByteUtil.bytesToUbyte(datalen);
		} else {
			return ByteUtil.bytesToUshort(datalen);
		}

	}

	/**
	 * 解析数据CRC
	 * 
	 * @param datalen
	 * @return
	 */
	public static byte parseCrc(byte[] data) {
		byte[] crc = CrcUtil.crc8Check(data);
		return crc[0];
	}

	/**
	 * 获取密钥算法及密钥
	 */
	public static String[] parsePW(byte[] bytes) {
		// byte[] date = new byte[2];// ByteUtil.bcd2Str(dates);

		ArrayUtils.reverse(bytes);
		
		String pwd = ByteUtil.bcd2Str(bytes);
		// pwd = StringUtils.reverse(pwd);
		// 密钥算法(BCD 编码)
		String alg = pwd.substring(0, 1);
		// 密钥（BCD 编码）
		String secret = pwd.substring(1, 4);
		return new String[] { alg, secret };
	}

	/**
	 * 从动站的时效性判断规则：
	 * 
	 * 如从动站的当前时间与Tp 中的启动帧发送时标之间的时间差 大于Tp 中的允许传输延时时间，从动站则舍弃该报文。
	 * 
	 * @return
	 */
	public static int parseTpDelay(byte tp) {
		return ByteUtil.bytesToUbyte(new byte[] { tp });
	}

	public static Date parseTpTime(byte[] tp) throws ParseException {
		Date curdate = new Date(System.currentTimeMillis());
		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMM");
		String yearMonth = sdf.format(curdate);

		ArrayUtils.reverse(tp);
		String sendtime = yearMonth + ByteUtil.bcd2Str(tp);
		SimpleDateFormat sdf2 = new SimpleDateFormat("yyyyMMddHHmmss");
		return sdf2.parse(sendtime);
	}

	/**
	 * 解析水资源消息报文
	 * 
	 * @param message
	 *            消息体
	 */
	public static void parseMessage(SzyMessage message) {
		SzyMessageHeader header = (SzyMessageHeader) message.getHeader();
		SzyMessageBody body = (SzyMessageBody) message.getBody();
		// parseC0(body);
		byte[] bytes = body.getContent();
		int len = bytes.length;
		int pos = 0;

		byte[] C = new byte[1];
		System.arraycopy(bytes, pos, C, 0, C.length);
		pos = pos + C.length;
		body.setControl(C[0]);

		byte[] A = new byte[5];
		System.arraycopy(bytes, pos, A, 0, A.length);
		pos = pos + A.length;
		body.setAddress(A);

		byte[] AFN = new byte[1];
		System.arraycopy(bytes, pos, AFN, 0, AFN.length);
		pos = pos + AFN.length;

		byte[] userdata = null;
		byte[] alarm = null;
		byte[] status = null;
		byte[] tp = null;
		// int[] control = parseControl(C[0]);
		if (AFN[0] == (byte) 0xc0) {

			userdata = new byte[len - pos - 4 - 5];
			System.arraycopy(bytes, pos, userdata, 0, userdata.length);
			pos = pos + userdata.length;

			alarm = new byte[2];
			System.arraycopy(bytes, pos, alarm, 0, alarm.length);
			pos = pos + alarm.length;

			status = new byte[2];
			System.arraycopy(bytes, pos, status, 0, status.length);
			pos = pos + status.length;

			tp = new byte[5];
			System.arraycopy(bytes, pos, tp, 0, tp.length);
			pos = pos + tp.length;

		}

		parseData(C[0], AFN[0], userdata);
		parseAlarm(status);
		parseStatus(status);
	}

	/**
	 * 解析水资源消息报文
	 * 
	 * @param bytes
	 *            消息字节数组
	 */
	public static BaseData parseMessageBody(byte[] data) throws Exception {

		System.out.println("====================解析报文数据=======================");
		System.out.println(">> 报文内容：" + ByteUtil.toHexString(data));
		System.out.println(">> 报文长度： " + data.length);

		// 1.1：解析数据长度
		int len = data.length;

		int pos = 0;

		byte control = data[0];
		int[] C = SzyParser.parseControl(control);
		System.out.println(">> 控制域：" + (C[0] == 1 ? "上行" : "下行") + "_" + C[0]
				+ " \t" + (C[1] == 0 ? "单帧" : "多帧") + "_" + C[1] + " \t"
				+ " 传输" + "_" + C[2] + "\t" + SzyConst.FUNC[C[3]]);
		pos = pos + 1;

		int amount = 0;
		int seq = 1;
		if (C[1] == 1) {// 表示多帧，在C控制位后需要多加一个字节
			byte[] SEQ = new byte[1];
			System.arraycopy(data, pos, SEQ, 0, SEQ.length);
			seq = ByteUtil.bytesToUbyte(SEQ);
			amount = 1;
			pos = pos + 1;
		}

		// 4.1：解析地址域A
		byte[] address = new byte[5];
		System.arraycopy(data, pos, address, 0, address.length);
		String A = SzyParser.parseAddress(address);
		pos = pos + address.length;
		System.out.println(">> 地址域：" + A);

		// 4.3：用户数据区
		byte[] afn = new byte[1];
		System.arraycopy(data, pos, afn, 0, afn.length);
		pos = pos + afn.length;
		System.out.println(">> 功能码：AFN "
				+ ByteUtil.toHexString(afn).toUpperCase() + " "
				+ SzyConst.AFN.get((byte) afn[0]));

		BodyUp userdata = new BodyUp();
		byte[] tempdata;
		byte[] alarm = null;
		byte[] status = null;
		byte[] pw = null;
		byte[] tp = null;

		// 构造返回数据
		BaseData basedata = new BaseData();
		basedata.setStcd(A);
		basedata.setFunc(ByteUtil.toHexString(afn));
		basedata.setAmount(amount);
		basedata.setSeq(seq);
		basedata.setWritetime(new Date(System.currentTimeMillis()));

		switch ((byte) afn[0]) {
		case (byte) 0x02:// 链路
			userdata.setAFN(afn[0]);
			tempdata = new byte[1];
			System.arraycopy(data, pos, tempdata, 0, tempdata.length);
			userdata.setData(tempdata);
			break;
		case (byte) 0x10:
			userdata = new BodyUp();
			userdata.setAFN(afn[0]);
			tempdata = new byte[5];
			System.arraycopy(data, pos, tempdata, 0, tempdata.length);
			userdata.setData(tempdata);
			pos = pos + tempdata.length;

			pw = new byte[2];
			System.arraycopy(data, pos, pw, 0, pw.length);
			pos = pos + pw.length;

			tp = new byte[5];
			System.arraycopy(data, pos, tp, 0, tp.length);
			pos = pos + tp.length;

			// 解析并返回
			basedata.setItems(parse50(tempdata));

			break;
		case (byte) 0x50:// 查询遥测终端或中继站地址
			userdata.setAFN(afn[0]);
			tempdata = new byte[5];
			System.arraycopy(data, pos, tempdata, 0, tempdata.length);
			userdata.setData(tempdata);

			// 返回数据
			basedata.setItems(parse50(tempdata));

			break;
		case (byte) 0x11:
			userdata.setAFN(afn[0]);
			tempdata = new byte[6];
			System.arraycopy(data, pos, tempdata, 0, tempdata.length);
			userdata.setData(tempdata);
			pos = pos + tempdata.length;

			pw = new byte[2];
			System.arraycopy(data, pos, pw, 0, pw.length);
			pos = pos + pw.length;

			tp = new byte[5];
			System.arraycopy(data, pos, tp, 0, tp.length);
			pos = pos + tp.length;

			// 返回数据
			basedata.setItems(parse51(tempdata));

			break;
		case (byte) 0x51:// 查询遥测终端或中继站时钟
			userdata.setAFN(afn[0]);
			tempdata = new byte[6];
			System.arraycopy(data, pos, tempdata, 0, tempdata.length);
			userdata.setData(tempdata);

			// 返回数据
			basedata.setItems(parse51(tempdata));
			break;
		case (byte) 0x12:
			userdata.setAFN(afn[0]);
			tempdata = new byte[1];
			System.arraycopy(data, pos, tempdata, 0, tempdata.length);
			userdata.setData(tempdata);
			pos = pos + tempdata.length;

			pw = new byte[2];
			System.arraycopy(data, pos, pw, 0, pw.length);
			pos = pos + pw.length;

			tp = new byte[5];
			System.arraycopy(data, pos, tp, 0, tp.length);
			pos = pos + tp.length;

			// 返回数据
			basedata.setItems(parse52(tempdata[0]));

			break;
		case (byte) 0x52:// 查询遥测终端的工作模式
			userdata.setAFN(afn[0]);
			tempdata = new byte[1];
			System.arraycopy(data, pos, tempdata, 0, tempdata.length);
			userdata.setData(tempdata);

			// 返回数据
			basedata.setItems(parse52(tempdata[0]));
			break;
		case (byte) 0xA1:
			userdata.setAFN(afn[0]);
			tempdata = new byte[30];
			System.arraycopy(data, pos, tempdata, 0, tempdata.length);
			userdata.setData(tempdata);
			pos = pos + tempdata.length;

			// 返回数据
			basedata.setItems(parse53(tempdata));

			pw = new byte[2];
			System.arraycopy(data, pos, pw, 0, pw.length);
			pos = pos + pw.length;

			tp = new byte[5];
			System.arraycopy(data, pos, tp, 0, tp.length);
			pos = pos + tp.length;
			break;
		case (byte) 0x53:// 查询遥测终端的数据自报种类及时间间隔
			userdata = new BodyUp();
			userdata.setAFN(afn[0]);
			tempdata = new byte[30];
			System.arraycopy(data, pos, tempdata, 0, tempdata.length);
			userdata.setData(tempdata);
			pos = pos + tempdata.length;

			// 返回数据
			basedata.setItems(parse53(tempdata));

			break;
		case (byte) 0xA0:
			userdata = new BodyUp();
			userdata.setAFN(afn[0]);
			tempdata = new byte[2];
			System.arraycopy(data, pos, tempdata, 0, tempdata.length);
			userdata.setData(tempdata);
			pos = pos + tempdata.length;

			pw = new byte[2];
			System.arraycopy(data, pos, pw, 0, pw.length);
			pos = pos + pw.length;

			tp = new byte[5];
			System.arraycopy(data, pos, tp, 0, tp.length);
			pos = pos + tp.length;

			// 返回数据
			basedata.setItems(parse54(tempdata));

			break;
		case (byte) 0x54:// 查询遥测站需查询的实时数据种类
			userdata = new BodyUp();
			userdata.setAFN(afn[0]);
			tempdata = new byte[2];
			System.arraycopy(data, pos, tempdata, 0, tempdata.length);
			userdata.setData(tempdata);
			pos = pos + tempdata.length;

			// 返回数据
			basedata.setItems(parse54(tempdata));

			break;
		case (byte) 0x15:
			userdata = new BodyUp();
			userdata.setAFN(afn[0]);
			tempdata = new byte[4];
			System.arraycopy(data, pos, tempdata, 0, tempdata.length);
			userdata.setData(tempdata);
			pos = pos + tempdata.length;

			// 返回数据
			basedata.setItems(parse55(tempdata));

			pw = new byte[2];
			System.arraycopy(data, pos, pw, 0, pw.length);
			pos = pos + pw.length;

			tp = new byte[5];
			System.arraycopy(data, pos, tp, 0, tp.length);
			pos = pos + tp.length;
			break;
		case (byte) 0x55:// 查询遥测终端最近成功充值量和现有剩余水量
			userdata = new BodyUp();
			userdata.setAFN(afn[0]);
			tempdata = new byte[9];
			System.arraycopy(data, pos, tempdata, 0, tempdata.length);
			userdata.setData(tempdata);
			pos = pos + tempdata.length;

			// 返回数据
			basedata.setItems(parse55(tempdata));

			break;
		case (byte) 0x16:// 设置遥测终端的剩余水量报警值
			userdata.setAFN(afn[0]);
			tempdata = new byte[8];
			System.arraycopy(data, pos, tempdata, 0, tempdata.length);
			userdata.setData(tempdata);
			pos = pos + tempdata.length;

			// 返回数据
			basedata.setItems(parse56(tempdata));

			break;
		case (byte) 0x56:// 查询遥测终端的剩余水量和报警值
			userdata = new BodyUp();
			userdata.setAFN(afn[0]);
			tempdata = new byte[8];
			System.arraycopy(data, pos, tempdata, 0, tempdata.length);
			userdata.setData(tempdata);
			pos = pos + tempdata.length;

			// 返回数据
			basedata.setItems(parse56(tempdata));

			break;
		case (byte) 0x17:
			userdata = new BodyUp();
			userdata.setAFN(afn[0]);
			tempdata = new byte[7];// （N*7 个字节BCD）
			System.arraycopy(data, pos, tempdata, 0, tempdata.length);
			userdata.setData(tempdata);
			pos = pos + tempdata.length;

			// 返回数据
			basedata.setItems(parse57(tempdata));

			pw = new byte[2];
			System.arraycopy(data, pos, pw, 0, pw.length);
			pos = pos + pw.length;

			tp = new byte[5];
			System.arraycopy(data, pos, tp, 0, tp.length);
			pos = pos + tp.length;

			break;
		case (byte) 0x57:// 查询遥测终端的水位基值、水位上下限
			userdata = new BodyUp();
			userdata.setAFN(afn[0]);
			tempdata = new byte[7];// （N*7 个字节BCD）
			System.arraycopy(data, pos, tempdata, 0, tempdata.length);
			userdata.setData(tempdata);
			pos = pos + tempdata.length;

			// 返回数据
			basedata.setItems(parse57(tempdata));

			// 还有两个字节的终端报警
			alarm = new byte[2];
			System.arraycopy(data, pos, alarm, 0, alarm.length);
			pos = pos + alarm.length;
			break;
		case (byte) 0x18:
		case (byte) 0x58:// 查询遥测终端水压上、下限值
			userdata = new BodyUp();
			userdata.setAFN(afn[0]);
			tempdata = new byte[8];// （N*8 个字节BCD）
			System.arraycopy(data, pos, tempdata, 0, tempdata.length);
			userdata.setData(tempdata);
			pos = pos + tempdata.length;

			// 返回数据
			basedata.setItems(parse58(tempdata));

			// 还有两个字节的终端报警
			alarm = new byte[2];
			System.arraycopy(data, pos, alarm, 0, alarm.length);
			pos = pos + alarm.length;

			break;
		case (byte) 0x19:
			userdata = new BodyUp();
			userdata.setAFN(afn[0]);
			tempdata = new byte[4];// (5＋N*4＋1 个字节)
			System.arraycopy(data, pos, tempdata, 0, tempdata.length);
			userdata.setData(tempdata);
			pos = pos + tempdata.length;

			// 返回数据
			basedata.setItems(parse59(tempdata));

			System.arraycopy(data, pos, pw, 0, pw.length);
			pos = pos + pw.length;

			System.arraycopy(data, pos, tp, 0, tp.length);
			pos = pos + tp.length;
			break;
		case (byte) 0x59:// 查询遥测终端水质参数种类、上限值
			userdata = new BodyUp();
			userdata.setAFN(afn[0]);
			tempdata = new byte[4];// (5＋N*4＋1 个字节)
			System.arraycopy(data, pos, tempdata, 0, tempdata.length);
			userdata.setData(tempdata);
			pos = pos + tempdata.length;

			// 返回数据
			basedata.setItems(parse59(tempdata));

			break;
		case (byte) 0x1A:
		case (byte) 0x5A:// 查询遥测终端水质参数种类、下限值
			userdata = new BodyUp();
			userdata.setAFN(afn[0]);
			tempdata = new byte[4];// (5＋N*4＋1 个字节)
			System.arraycopy(data, pos, tempdata, 0, tempdata.length);
			userdata.setData(tempdata);
			pos = pos + tempdata.length;

			break;
		case (byte) 0x5F:// 查询水泵电机实时工作数据（AFN=5FH）
			userdata = new BodyUp();
			userdata.setAFN(afn[0]);
			tempdata = new byte[12];// (5＋N*4＋1 个字节)
			System.arraycopy(data, pos, tempdata, 0, tempdata.length);
			userdata.setData(tempdata);
			pos = pos + tempdata.length;

			parse5F(tempdata);

			break;
		case (byte) 0x1B:
			userdata = new BodyUp();
			userdata.setAFN(afn[0]);
			tempdata = new byte[5];// （N*5 个字节BCD）
			System.arraycopy(data, pos, tempdata, 0, tempdata.length);
			userdata.setData(tempdata);
			pos = pos + tempdata.length;

			parse1B(tempdata);

			break;
		case (byte) 0x1C:
		case (byte) 0x60:// 60H 查询终端站转发中继引导码长值
			break;
		case (byte) 0x1D:// 62H 查询中继站转发终端地址
		case (byte) 0x62:// 62H 查询中继站转发终端地址
			break;
		case (byte) 0x1E:
		case (byte) 0x63:// 查询中继站状态和切换记录
			break;
		case (byte) 0x1F:
			userdata = new BodyUp();
			userdata.setAFN(afn[0]);
			tempdata = new byte[5];// （N*5 个字节BCD）
			System.arraycopy(data, pos, tempdata, 0, tempdata.length);
			userdata.setData(tempdata);
			pos = pos + tempdata.length;

			System.arraycopy(data, pos, pw, 0, pw.length);
			pos = pos + pw.length;

			System.arraycopy(data, pos, tp, 0, tp.length);
			pos = pos + tp.length;

			break;
		case (byte) 0x64:// 查询遥测终端流量参数上限值
			userdata = new BodyUp();
			userdata.setAFN(afn[0]);
			tempdata = new byte[5];// （N*5 个字节BCD＋2 字节终端报警）
			System.arraycopy(data, pos, tempdata, 0, tempdata.length);
			userdata.setData(tempdata);
			pos = pos + tempdata.length;
			break;
		case (byte) 0xB0:// 查询遥测终端实时值（AFN=B0H）
			userdata = new BodyUp();
			userdata.setAFN(afn[0]);

			tempdata = new byte[len - pos - 4];// 此处无TP
			System.arraycopy(data, pos, tempdata, 0, tempdata.length);
			userdata.setData(tempdata);
			pos = pos + tempdata.length;
			userdata.setData(tempdata);

			alarm = new byte[2];
			System.arraycopy(data, pos, alarm, 0, alarm.length);
			userdata.setAlarm(alarm);
			pos = pos + alarm.length;

			status = new byte[2];
			System.arraycopy(data, pos, status, 0, status.length);
			userdata.setStatus(status);
			pos = pos + status.length;

			basedata.setItems(parseData(control, afn[0], userdata.getData()));
			parseAlarm(alarm);
			parseStatus(status);

			break;

		case (byte) 0x96:// 修改遥测终端密码（AFN=96H）
			userdata = new BodyUp();
			userdata.setAFN(afn[0]);
			tempdata = new byte[2];// 此处无TP
			System.arraycopy(data, pos, tempdata, 0, tempdata.length);
			userdata.setData(tempdata);

			// parse96(tempdata);

			break;
		case (byte) 0xC0:// 遥测终端自报实时数据（AFN=C0H）
			userdata = new BodyUp();
			userdata.setAFN(afn[0]);

			tempdata = new byte[len - pos - 4 - 5];
			System.arraycopy(data, pos, tempdata, 0, tempdata.length);
			userdata.setData(tempdata);
			pos = pos + tempdata.length;

			alarm = new byte[2];
			System.arraycopy(data, pos, alarm, 0, alarm.length);
			pos = pos + alarm.length;
			userdata.setAlarm(alarm);

			status = new byte[2];
			System.arraycopy(data, pos, status, 0, status.length);
			userdata.setStatus(status);
			pos = pos + status.length;

			tp = new byte[5];
			System.arraycopy(data, pos, tp, 0, tp.length);
			userdata.setTp(tp);
			pos = pos + tp.length;

			basedata.setItems(parseData(control, afn[0], userdata.getData()));
			parseAlarm(alarm);
			parseStatus(status);
			break;
		case (byte) 0x81:// 随机自报报警数据（AFN=81H）
			userdata = new BodyUp();
			userdata.setAFN(afn[0]);

			alarm = new byte[2];
			System.arraycopy(data, pos, alarm, 0, alarm.length);
			pos = pos + alarm.length;
			userdata.setAlarm(alarm);

			tempdata = new byte[len - pos - 2 - 5];
			System.arraycopy(data, pos, tempdata, 0, tempdata.length);
			userdata.setData(tempdata);
			pos = pos + tempdata.length;

			status = new byte[2];
			System.arraycopy(data, pos, status, 0, status.length);
			userdata.setStatus(status);
			pos = pos + status.length;

			tp = new byte[5];
			System.arraycopy(data, pos, tp, 0, tp.length);
			userdata.setTp(tp);
			pos = pos + tp.length;

			basedata.setItems(parseData(control, afn[0], userdata.getData()));
			parseAlarm(alarm);
			parseStatus(status);
			break;
		case (byte) 0x82:// 人工置数（AFN=82H）

			break;
		default:

		}

		if (tp != null) {
			basedata.setViewtime(parseTpTime(new byte[] { tp[0], tp[1], tp[2],
					tp[3] }));
		}

		basedata.setWritetime(new Date(System.currentTimeMillis()));

		return basedata;

	}

	/**
	 * 解析水资源消息报文
	 * 
	 * @param bytes
	 *            消息字节数组
	 */
	public static void parseMessage(byte[] bytes) {
		// 第一步：解析报文
		byte startMsgBit = bytes[0];
		byte datalen = bytes[1];
		byte startBodyBit = bytes[2];

		// 1.1：解析数据长度
		int len = SzyParser.parseDataLen(new byte[] { datalen });

		// 1.2：存放正文内容
		byte[] data = new byte[len];
		System.arraycopy(bytes, 3, data, 0, len);

		// 1.3：获取CRC校验码
		byte cs = bytes[3 + len];

		// 1.4：获取结束符
		byte endBit = bytes[bytes.length - 1];

		// -----------------------------------------------------------
		// 第三步：封装报文
		// 2.1：构建消息头
		SzyMessageHeader header = new SzyMessageHeader();
		header.setStartBit(new byte[] { startMsgBit });
		header.setBodySize(new byte[] { datalen });
		header.setBodyStartBit(new byte[] { startBodyBit });

		// 2.2：构建消息体
		SzyMessage message = new SzyMessage();
		message.setHeader(header);

		// 2.2：根据功能码，构建body体
		IMessageBody body = new SzyMessageBody();
		body.setContents(data);
		message.setBody(body);
		message.setEOF(endBit);
		message.setCRC(new byte[] { cs });

		// -----------------------------------------------------------
		// 第四步：解析数据体
		// 4.1：解析控制域C

		System.out.println("====================解析报文数据=======================");
		System.out.println(">> 报文内容：" + ByteUtil.toHexString(bytes));
		System.out.println(">> 报文长度： " + bytes.length + " 数据区长度：" + len);
		int pos = 0;

		byte control = data[0];
		int[] C = SzyParser.parseControl(control);
		System.out.println(">> 控制域：" + (C[0] == 1 ? "上行" : "下行") + "_" + C[0]
				+ " \t" + (C[1] == 0 ? "单帧" : "多帧") + "_" + C[1] + " \t"
				+ " 传输" + "_" + C[2] + "\t" + SzyConst.FUNC[C[3]]);
		pos = pos + 1;

		int amount = 0;
		int seq = 1;
		if (C[1] == 1) {// 表示多帧，在C控制位后需要多加一个字节
			byte[] SEQ = new byte[1];
			System.arraycopy(data, pos, SEQ, 0, SEQ.length);
			seq = ByteUtil.bytesToUbyte(SEQ);
			amount = 1;
			pos = pos + 1;
		}

		// 4.1：解析地址域A
		byte[] address = new byte[5];
		System.arraycopy(data, pos, address, 0, address.length);
		String A = SzyParser.parseAddress(address);
		pos = pos + address.length;
		System.out.println(">> 地址域：" + A);

		// 4.3：用户数据区
		byte[] afn = new byte[1];
		System.arraycopy(data, pos, afn, 0, afn.length);
		pos = pos + afn.length;
		System.out.println(">> 功能码：AFN "
				+ ByteUtil.toHexString(afn).toUpperCase() + " "
				+ SzyConst.AFN.get((byte) afn[0]));

		BodyUp userdata = new BodyUp();
		byte[] tempdata;
		byte[] alarm = null;
		byte[] status = null;
		byte[] pw = null;
		byte[] tp = null;

		// 构造返回数据
		BaseData basedata = new BaseData();
		basedata.setStcd(A);
		basedata.setFunc(ByteUtil.toHexString(afn));
		basedata.setAmount(amount);
		basedata.setSeq(seq);

		switch ((byte) afn[0]) {
		case (byte) 0x02:// 链路
			userdata.setAFN(afn[0]);
			tempdata = new byte[1];
			System.arraycopy(data, pos, tempdata, 0, tempdata.length);
			userdata.setData(tempdata);
			break;
		case (byte) 0x10:
			userdata = new BodyUp();
			userdata.setAFN(afn[0]);
			tempdata = new byte[5];
			System.arraycopy(data, pos, tempdata, 0, tempdata.length);
			userdata.setData(tempdata);
			pos = pos + tempdata.length;

			pw = new byte[2];
			System.arraycopy(data, pos, pw, 0, pw.length);
			pos = pos + pw.length;

			tp = new byte[5];
			System.arraycopy(data, pos, tp, 0, tp.length);
			pos = pos + tp.length;

			// 解析并返回
			basedata.setItems(parse50(tempdata));

			break;
		case (byte) 0x50:// 查询遥测终端或中继站地址
			userdata.setAFN(afn[0]);
			tempdata = new byte[5];
			System.arraycopy(data, pos, tempdata, 0, tempdata.length);
			userdata.setData(tempdata);

			// 返回数据
			basedata.setItems(parse50(tempdata));

			break;
		case (byte) 0x11:
			userdata.setAFN(afn[0]);
			tempdata = new byte[6];
			System.arraycopy(data, pos, tempdata, 0, tempdata.length);
			userdata.setData(tempdata);
			pos = pos + tempdata.length;

			pw = new byte[2];
			System.arraycopy(data, pos, pw, 0, pw.length);
			pos = pos + pw.length;

			tp = new byte[5];
			System.arraycopy(data, pos, tp, 0, tp.length);
			pos = pos + tp.length;

			// 返回数据
			basedata.setItems(parse51(tempdata));

			break;
		case (byte) 0x51:// 查询遥测终端或中继站时钟
			userdata.setAFN(afn[0]);
			tempdata = new byte[6];
			System.arraycopy(data, pos, tempdata, 0, tempdata.length);
			userdata.setData(tempdata);

			// 返回数据
			basedata.setItems(parse51(tempdata));
			break;
		case (byte) 0x12:
			userdata.setAFN(afn[0]);
			tempdata = new byte[1];
			System.arraycopy(data, pos, tempdata, 0, tempdata.length);
			userdata.setData(tempdata);
			pos = pos + tempdata.length;

			pw = new byte[2];
			System.arraycopy(data, pos, pw, 0, pw.length);
			pos = pos + pw.length;

			tp = new byte[5];
			System.arraycopy(data, pos, tp, 0, tp.length);
			pos = pos + tp.length;

			// 返回数据
			basedata.setItems(parse52(tempdata[0]));

			break;
		case (byte) 0x52:// 查询遥测终端的工作模式
			userdata.setAFN(afn[0]);
			tempdata = new byte[1];
			System.arraycopy(data, pos, tempdata, 0, tempdata.length);
			userdata.setData(tempdata);

			// 返回数据
			basedata.setItems(parse52(tempdata[0]));
			break;
		case (byte) 0xA1:
			userdata.setAFN(afn[0]);
			tempdata = new byte[30];
			System.arraycopy(data, pos, tempdata, 0, tempdata.length);
			userdata.setData(tempdata);
			pos = pos + tempdata.length;

			// 返回数据
			basedata.setItems(parse53(tempdata));

			pw = new byte[2];
			System.arraycopy(data, pos, pw, 0, pw.length);
			pos = pos + pw.length;

			tp = new byte[5];
			System.arraycopy(data, pos, tp, 0, tp.length);
			pos = pos + tp.length;
			break;
		case (byte) 0x53:// 查询遥测终端的数据自报种类及时间间隔
			userdata = new BodyUp();
			userdata.setAFN(afn[0]);
			tempdata = new byte[30];
			System.arraycopy(data, pos, tempdata, 0, tempdata.length);
			userdata.setData(tempdata);
			pos = pos + tempdata.length;

			// 返回数据
			basedata.setItems(parse53(tempdata));

			break;
		case (byte) 0xA0:
			userdata = new BodyUp();
			userdata.setAFN(afn[0]);
			tempdata = new byte[2];
			System.arraycopy(data, pos, tempdata, 0, tempdata.length);
			userdata.setData(tempdata);
			pos = pos + tempdata.length;

			pw = new byte[2];
			System.arraycopy(data, pos, pw, 0, pw.length);
			pos = pos + pw.length;

			tp = new byte[5];
			System.arraycopy(data, pos, tp, 0, tp.length);
			pos = pos + tp.length;

			// 返回数据
			basedata.setItems(parse54(tempdata));

			break;
		case (byte) 0x54:// 查询遥测站需查询的实时数据种类
			userdata = new BodyUp();
			userdata.setAFN(afn[0]);
			tempdata = new byte[2];
			System.arraycopy(data, pos, tempdata, 0, tempdata.length);
			userdata.setData(tempdata);
			pos = pos + tempdata.length;

			// 返回数据
			basedata.setItems(parse54(tempdata));

			break;
		case (byte) 0x15:
			userdata = new BodyUp();
			userdata.setAFN(afn[0]);
			tempdata = new byte[4];
			System.arraycopy(data, pos, tempdata, 0, tempdata.length);
			userdata.setData(tempdata);
			pos = pos + tempdata.length;

			// 返回数据
			basedata.setItems(parse55(tempdata));

			pw = new byte[2];
			System.arraycopy(data, pos, pw, 0, pw.length);
			pos = pos + pw.length;

			tp = new byte[5];
			System.arraycopy(data, pos, tp, 0, tp.length);
			pos = pos + tp.length;
			break;
		case (byte) 0x55:// 查询遥测终端最近成功充值量和现有剩余水量
			userdata = new BodyUp();
			userdata.setAFN(afn[0]);
			tempdata = new byte[9];
			System.arraycopy(data, pos, tempdata, 0, tempdata.length);
			userdata.setData(tempdata);
			pos = pos + tempdata.length;

			// 返回数据
			basedata.setItems(parse55(tempdata));

			break;
		case (byte) 0x16:// 设置遥测终端的剩余水量报警值
			userdata.setAFN(afn[0]);
			tempdata = new byte[8];
			System.arraycopy(data, pos, tempdata, 0, tempdata.length);
			userdata.setData(tempdata);
			pos = pos + tempdata.length;

			// 返回数据
			basedata.setItems(parse56(tempdata));

			break;
		case (byte) 0x56:// 查询遥测终端的剩余水量和报警值
			userdata = new BodyUp();
			userdata.setAFN(afn[0]);
			tempdata = new byte[8];
			System.arraycopy(data, pos, tempdata, 0, tempdata.length);
			userdata.setData(tempdata);
			pos = pos + tempdata.length;

			// 返回数据
			basedata.setItems(parse56(tempdata));

			break;
		case (byte) 0x17:
			userdata = new BodyUp();
			userdata.setAFN(afn[0]);
			tempdata = new byte[7];// （N*7 个字节BCD）
			System.arraycopy(data, pos, tempdata, 0, tempdata.length);
			userdata.setData(tempdata);
			pos = pos + tempdata.length;

			// 返回数据
			basedata.setItems(parse57(tempdata));

			pw = new byte[2];
			System.arraycopy(data, pos, pw, 0, pw.length);
			pos = pos + pw.length;

			tp = new byte[5];
			System.arraycopy(data, pos, tp, 0, tp.length);
			pos = pos + tp.length;

			break;
		case (byte) 0x57:// 查询遥测终端的水位基值、水位上下限
			userdata = new BodyUp();
			userdata.setAFN(afn[0]);
			tempdata = new byte[7];// （N*7 个字节BCD）
			System.arraycopy(data, pos, tempdata, 0, tempdata.length);
			userdata.setData(tempdata);
			pos = pos + tempdata.length;

			// 返回数据
			basedata.setItems(parse57(tempdata));

			// 还有两个字节的终端报警
			alarm = new byte[2];
			System.arraycopy(data, pos, alarm, 0, alarm.length);
			pos = pos + alarm.length;
			break;
		case (byte) 0x18:
		case (byte) 0x58:// 查询遥测终端水压上、下限值
			userdata = new BodyUp();
			userdata.setAFN(afn[0]);
			tempdata = new byte[8];// （N*8 个字节BCD）
			System.arraycopy(data, pos, tempdata, 0, tempdata.length);
			userdata.setData(tempdata);
			pos = pos + tempdata.length;

			// 返回数据
			basedata.setItems(parse58(tempdata));

			// 还有两个字节的终端报警
			alarm = new byte[2];
			System.arraycopy(data, pos, alarm, 0, alarm.length);
			pos = pos + alarm.length;

			break;
		case (byte) 0x19:
			userdata = new BodyUp();
			userdata.setAFN(afn[0]);
			tempdata = new byte[4];// (5＋N*4＋1 个字节)
			System.arraycopy(data, pos, tempdata, 0, tempdata.length);
			userdata.setData(tempdata);
			pos = pos + tempdata.length;

			// 返回数据
			basedata.setItems(parse59(tempdata));

			System.arraycopy(data, pos, pw, 0, pw.length);
			pos = pos + pw.length;

			System.arraycopy(data, pos, tp, 0, tp.length);
			pos = pos + tp.length;
			break;
		case (byte) 0x59:// 查询遥测终端水质参数种类、上限值
			userdata = new BodyUp();
			userdata.setAFN(afn[0]);
			tempdata = new byte[4];// (5＋N*4＋1 个字节)
			System.arraycopy(data, pos, tempdata, 0, tempdata.length);
			userdata.setData(tempdata);
			pos = pos + tempdata.length;

			// 返回数据
			basedata.setItems(parse59(tempdata));

			break;
		case (byte) 0x1A:
		case (byte) 0x5A:// 查询遥测终端水质参数种类、下限值
			userdata = new BodyUp();
			userdata.setAFN(afn[0]);
			tempdata = new byte[4];// (5＋N*4＋1 个字节)
			System.arraycopy(data, pos, tempdata, 0, tempdata.length);
			userdata.setData(tempdata);
			pos = pos + tempdata.length;

			break;
		case (byte) 0x5F:// 查询水泵电机实时工作数据（AFN=5FH）
			userdata = new BodyUp();
			userdata.setAFN(afn[0]);
			tempdata = new byte[12];// (5＋N*4＋1 个字节)
			System.arraycopy(data, pos, tempdata, 0, tempdata.length);
			userdata.setData(tempdata);
			pos = pos + tempdata.length;

			parse5F(tempdata);

			break;
		case (byte) 0x1B:
			userdata = new BodyUp();
			userdata.setAFN(afn[0]);
			tempdata = new byte[5];// （N*5 个字节BCD）
			System.arraycopy(data, pos, tempdata, 0, tempdata.length);
			userdata.setData(tempdata);
			pos = pos + tempdata.length;

			parse1B(tempdata);

			break;
		case (byte) 0x1C:
		case (byte) 0x60:// 60H 查询终端站转发中继引导码长值
			break;
		case (byte) 0x1D:// 62H 查询中继站转发终端地址
		case (byte) 0x62:// 62H 查询中继站转发终端地址
			break;
		case (byte) 0x1E:
		case (byte) 0x63:// 查询中继站状态和切换记录
			break;
		case (byte) 0x1F:
			userdata = new BodyUp();
			userdata.setAFN(afn[0]);
			tempdata = new byte[5];// （N*5 个字节BCD）
			System.arraycopy(data, pos, tempdata, 0, tempdata.length);
			userdata.setData(tempdata);
			pos = pos + tempdata.length;

			System.arraycopy(data, pos, pw, 0, pw.length);
			pos = pos + pw.length;

			System.arraycopy(data, pos, tp, 0, tp.length);
			pos = pos + tp.length;

			break;
		case (byte) 0x64:// 查询遥测终端流量参数上限值
			userdata = new BodyUp();
			userdata.setAFN(afn[0]);
			tempdata = new byte[5];// （N*5 个字节BCD＋2 字节终端报警）
			System.arraycopy(data, pos, tempdata, 0, tempdata.length);
			userdata.setData(tempdata);
			pos = pos + tempdata.length;
			break;
		case (byte) 0xB0:// 查询遥测终端实时值（AFN=B0H）
			userdata = new BodyUp();
			userdata.setAFN(afn[0]);

			tempdata = new byte[len - pos - 4];// 此处无TP
			System.arraycopy(data, pos, tempdata, 0, tempdata.length);
			userdata.setData(tempdata);
			pos = pos + tempdata.length;
			userdata.setData(tempdata);

			alarm = new byte[2];
			System.arraycopy(data, pos, alarm, 0, alarm.length);
			userdata.setAlarm(alarm);
			pos = pos + alarm.length;

			status = new byte[2];
			System.arraycopy(data, pos, status, 0, status.length);
			userdata.setStatus(status);
			pos = pos + status.length;

			parseData(control, afn[0], userdata.getData());
			parseAlarm(alarm);
			parseStatus(status);

			break;
		case (byte) 0xC0:// 遥测终端自报实时数据（AFN=C0H）
			userdata = new BodyUp();
			userdata.setAFN(afn[0]);

			tempdata = new byte[len - pos - 4 - 5];
			System.arraycopy(data, pos, tempdata, 0, tempdata.length);
			userdata.setData(tempdata);
			pos = pos + tempdata.length;

			alarm = new byte[2];
			System.arraycopy(data, pos, alarm, 0, alarm.length);
			pos = pos + alarm.length;
			userdata.setAlarm(alarm);

			status = new byte[2];
			System.arraycopy(data, pos, status, 0, status.length);
			userdata.setStatus(status);
			pos = pos + status.length;

			tp = new byte[5];
			System.arraycopy(data, pos, tp, 0, tp.length);
			userdata.setTp(tp);
			pos = pos + tp.length;

			// 返回数据
			basedata.setItems(parseData(control, afn[0], userdata.getData()));

			parseAlarm(alarm);
			parseStatus(status);
			break;
		case (byte) 0x81:// 随机自报报警数据（AFN=81H）
			userdata = new BodyUp();
			userdata.setAFN(afn[0]);

			alarm = new byte[2];
			System.arraycopy(data, pos, alarm, 0, alarm.length);
			pos = pos + alarm.length;
			userdata.setAlarm(alarm);

			tempdata = new byte[len - pos - 2 - 5];
			System.arraycopy(data, pos, tempdata, 0, tempdata.length);
			userdata.setData(tempdata);
			pos = pos + tempdata.length;

			status = new byte[2];
			System.arraycopy(data, pos, status, 0, status.length);
			userdata.setStatus(status);
			pos = pos + status.length;

			tp = new byte[5];
			System.arraycopy(data, pos, tp, 0, tp.length);
			userdata.setTp(tp);
			pos = pos + tp.length;

			basedata.setItems(parseData(control, afn[0], userdata.getData()));
			parseAlarm(alarm);
			parseStatus(status);
			break;
		default:

		}

		// basedata.setViewtime();
		// basedata.set
	}

	/**
	 * 设置终端站水量的表底（初始）值（AFN=1BH）
	 * 
	 * @param data
	 * @return
	 */
	public static IData parse1B(byte[] data) {
		int len = data.length;
		int count = len / 5;

		int[] val = new int[count];

		for (int i = 0; i < count; i++) {
			// 水位基值
			byte[] temp = new byte[5];
			System.arraycopy(data, i * 5, temp, 0, 5);
			ArrayUtils.reverse(temp);
			int flag = (byte) (temp[0] & 0x80) >> 7;
			if (flag == 1) {
				flag = -1;
			} else {
				flag = 1;
			}
			temp[0] = (byte) (temp[0] & 0x7F);

			String value = ByteUtil.bcd2Str(data);
			val[i] = Integer.parseInt(value) * flag;

		}

		Data1B d = new Data1B();
		d.setBase(val);

		return d;
	}

	/**
	 * 设置遥测终端的流量参数上限值
	 * 
	 * @param data
	 * @return
	 */
	public static IData parse1F(byte[] data) {

		int len = data.length;
		int count = len / 5;

		double[] val = new double[count];

		for (int i = 0; i < count; i++) {
			// 水位基值
			byte[] temp = new byte[5];
			System.arraycopy(data, i * 5, temp, 0, 5);
			ArrayUtils.reverse(temp);
			int flag = (byte) (temp[0] & 0xF0) >> 4;
			if (flag == 15) {
				flag = -1;
			} else {
				flag = 1;
			}
			temp[0] = (byte) (temp[0] & 0x0F);

			String value = ByteUtil.bcd2Str(data);
			String lvalue = value.substring(0, 7);
			String rvalue = value.substring(7, 10);
			String pvalue = lvalue + "." + rvalue;
			val[i] = Double.parseDouble(pvalue) * flag;
		}

		Data1F d = new Data1F();
		d.setQ(val);

		return d;
	}

	/**
	 * 解析遥测终端或中继站地址
	 * 
	 * @param bytes
	 */
	public static IData parse50(byte[] bytes) {
		Data50 d = new Data50();
		d.setStcd(parseAddress(bytes));
		return d;
	}

	/**
	 * 解析遥测终端或中继站时钟
	 * 
	 * @param bytes
	 */
	public static IData parse51(byte[] bytes) {
		Data51 d = new Data51();
		d.setClock(parseClock(bytes));
		return d;
	}

	/**
	 * 
	 * 解析工作模式
	 * 
	 * 工作模式类型=00B，设置遥测终端在兼容工作状态；
	 * 
	 * 工作模式类型=01H，设置遥测终端在自报工作状态；
	 * 
	 * 工作模式类型=02H，设置遥测终端在查询/应答工作状态；
	 * 
	 * 工作模式类型=03H，遥测终端在调试/维修状态。
	 * 
	 * @param data
	 * @return
	 */
	public static IData parse52(byte data) {

		Data52 d = new Data52();

		d.setMode(ByteUtil.toHexString(data));

		String text = "";
		switch (data) {
		case (byte) 0x00:
			text = "遥测终端在兼容工作状态";
			break;
		case (byte) 0x01:
			text = "遥测终端在自报工作状态";
			break;
		case (byte) 0x02:
			text = "遥测终端在查询/应答工作状态";
			break;
		case (byte) 0x03:
			text = "遥测终端在调试/维修状态";
			break;
		}
		d.setText(text);
		return d;
	}

	/**
	 * 解析遥测终端的数据自报种类及时间间隔
	 * 
	 * 1为主动上报，0不为上报
	 * 
	 * 1) D0——雨量数据 ********* 2) D1——水位数据
	 * 
	 * 3) D2——流量（水量）数据 ** 4) D3——流速数据
	 * 
	 * 5) D4——闸位数据 ********* 6) D5——功率数据
	 * 
	 * 7) D6——气压数据 ********* 8) D7——风速（风向）
	 * 
	 * 9) D8——水温数据********* 10) D9——水质数据
	 * 
	 * 11) D10——土壤含水率数据* 12) D11——蒸发量数据
	 * 
	 * 13) D12——报警或状态数据 * 14) D13——水压数据
	 * 
	 * 15) D14——D15 备用。
	 * 
	 * @param data
	 * @return
	 */
	public static IData parse53(byte[] data) {

		Data53 d = new Data53();

		int[] result = new int[16];

		byte[] mode = new byte[2];
		System.arraycopy(data, 2, mode, 0, 2);
		ArrayUtils.reverse(mode);
		String modestr = ByteUtil.toBinaryString(mode);

		for (int i = 0; i < 14; i++) {
			String flag = modestr.substring(i, i + 1);
			if (flag.equals("1")) {// 主动上报

				byte[] temp = new byte[2];
				System.arraycopy(data, 2 + i * 2, temp, 0, 2);
				String interval = ByteUtil.bcd2Str(temp);

				result[i] = Integer.parseInt(interval);

			} else {
				result[i] = 0;
			}
		}

		d.setInterval(result);

		return d;
	}

	/**
	 * 解析遥测站需查询的实时数据种类
	 * 
	 * 1为查询，0不查询
	 * 
	 * 1) D0——雨量数据 ********* 2) D1——水位数据
	 * 
	 * 3) D2——流量（水量）数据 ** 4) D3——流速数据
	 * 
	 * 5) D4——闸位数据 ********* 6) D5——功率数据
	 * 
	 * 7) D6——气压数据 ********* 8) D7——风速（风向）
	 * 
	 * 9) D8——水温数据********* 10) D9——水质数据
	 * 
	 * 11) D10——土壤含水率数据* 12) D11——蒸发量数据
	 * 
	 * 13) D12——终端内存数据 ** 14) D13——固态存储数据
	 * 
	 * 15) D14——水压数据
	 * 
	 * 
	 * @param data
	 */
	public static IData parse54(byte[] data) {
		ArrayUtils.reverse(data);
		String modestr = ByteUtil.toBinaryString(data);

		int[] result = new int[16];
		for (int i = 0; i < 16; i++) {
			String flag = modestr.substring(i, i + 1);
			if (flag.equals("1")) {
				result[i] = 1;
			} else {
				result[i] = 0;
			}
		}

		Data54 d = new Data54();
		d.setInterval(result);
		return d;
	}

	/**
	 * 查询遥测终端最近成功充值量和现有剩余水量
	 * 
	 * @param data
	 */
	public static IData parse55(byte[] data) {

		Data55 d = new Data55();
		// 最近成功充值量
		byte[] A = new byte[4];
		System.arraycopy(data, 0, A, 0, 4);
		ArrayUtils.reverse(A);
		String aval = ByteUtil.bcd2Str(A);
		d.setPay(Integer.parseInt(aval));

		// 现有剩余水量
		byte[] B = new byte[5];
		System.arraycopy(data, 4, B, 0, 5);
		ArrayUtils.reverse(B);

		int flag = (byte) (B[0] & 0x80) >> 7;
		if (flag == 1) {
			flag = -1;
		} else {
			flag = 1;
		}
		B[0] = (byte) (B[0] & 0x7F);
		String bval = ByteUtil.bcd2Str(B);
		d.setRemain(Integer.parseInt(bval) * flag);

		return d;
	}

	/**
	 * 解析遥测终端的剩余水量和报警值（AFN=56H）
	 * 
	 * @param data
	 */
	public static IData parse56(byte[] data) {
		Data56 d = new Data56();
		// 报警值
		byte[] alarm = new byte[3];
		System.arraycopy(data, 0, alarm, 0, 3);
		ArrayUtils.reverse(alarm);
		String aval = ByteUtil.bcd2Str(alarm);
		d.setAlarm(Integer.parseInt(aval));

		// 现有剩余水量
		byte[] B = new byte[5];
		System.arraycopy(data, 3, B, 0, 5);
		ArrayUtils.reverse(B);

		int flag = (byte) (B[0] & 0x80) >> 7;
		if (flag == 1) {
			flag = -1;
		} else {
			flag = 1;
		}
		B[0] = (byte) (B[0] & 0x7F);
		String bval = ByteUtil.bcd2Str(B);
		d.setReamin(Integer.parseInt(bval) * flag);
		return d;
	}

	/**
	 * 解析遥测终端的水位基值、水位上下限
	 * 
	 * @param data
	 */
	public static IData parse57(byte[] data) {

		int len = data.length;
		int count = len / 7;

		Data57Item[] items = new Data57Item[count];

		for (int i = 0; i < count; i++) {

			items[i] = new Data57Item();

			// 水位基值
			byte[] base = new byte[3];
			System.arraycopy(data, 0, base, 0, 3);
			ArrayUtils.reverse(base);
			int flag = (byte) (base[0] & 0x80) >> 7;
			if (flag == 1) {
				flag = -1;
			} else {
				flag = 1;
			}
			base[0] = (byte) (base[0] & 0x7F);
			items[i].setBase(convertDecimal(base, 6, 4) * flag);

			// 水位上限
			byte[] toplimit = new byte[2];
			System.arraycopy(data, 3, toplimit, 0, 2);
			ArrayUtils.reverse(toplimit);
			items[i].setToplimit(convertDecimal(toplimit, 4, 2));

			// 水位下限
			byte[] lowlimit = new byte[2];
			System.arraycopy(data, 5, lowlimit, 0, 2);
			ArrayUtils.reverse(lowlimit);
			items[i].setLowlimit(convertDecimal(lowlimit, 4, 2));

		}

		Data57 d = new Data57();
		d.setItems(items);
		return d;

	}

	/**
	 * 解析遥测终端水压上、下限值（AFN=58H）
	 * 
	 * @param data
	 */
	public static IData parse58(byte[] data) {

		int len = data.length;
		int count = len / 8;

		Data58Item[] items = new Data58Item[count];

		for (int i = 0; i < count; i++) {

			items[i] = new Data58Item();
			// 水压上限
			byte[] toplimit = new byte[4];
			System.arraycopy(data, 0, toplimit, 0, 4);
			ArrayUtils.reverse(toplimit);
			items[i].setToplimit(convertDecimal(toplimit, 8, 5));

			// 水压下限
			byte[] lowlimit = new byte[4];
			System.arraycopy(data, 4, lowlimit, 0, 4);
			ArrayUtils.reverse(lowlimit);
			items[i].setLowlimit(convertDecimal(lowlimit, 8, 5));
		}

		Data58 d = new Data58();
		d.setItems(items);
		return d;

	}

	private static String convertSZ(byte[] data) {
		String binstr = ByteUtil.toBinaryString(data);
		int len = binstr.length() / 8;
		String result = "";
		for (int i = 0; i < len; i++) {
			String tmpstr = binstr.substring(i * 8, (i + 1) * 8);
			result = result + StringUtils.reverse(tmpstr);
		}
		return result;
	}
	
	/**
	 * 解析遥测终端水质参数种类、上限值（AFN=59H）
	 * 
	 * @param data
	 */
	public static IData parse59(byte[] data) {

		// 数据域中前5 个字节是本遥测终端监测的水质参数种类
		byte[] kind = new byte[5];
		System.arraycopy(data, 0, kind, 0, 5);
		String kindstr = convertSZ(kind);
		
		int pos = 5;
		double[] val = new double[40];
		for (int i = 0, len = kindstr.length(); i < len; i++) {
			String bit = kindstr.substring(i, i + 1);
			if (bit.equals("1")) { // 对应位置1 则监测，清0 则不监测，
				// 查找位置
				DataType dt = SzyConst.SZ.get(i);
				int blen = dt.getBlen();
				byte[] temp = new byte[blen];
				System.arraycopy(data, pos, temp, 0, blen);
				pos = pos + blen;

				ArrayUtils.reverse(temp);

				String value = ByteUtil.bcd2Str(temp);
				int dpos = blen * 2 - dt.getDecimal();
				String lvalue = value.substring(0, dpos);
				String rvalue = value.substring(dpos, blen * 2);
				String pvalue = lvalue + "." + rvalue;
				val[i] = Double.parseDouble(pvalue);

			}
		}

		Data59 d = new Data59();
		d.setSz(val);
		return d;

	}

	/**
	 * 解析遥测终端水质参数种类、下限值（AFN=5AH）
	 * 
	 * @param data
	 */
	public static IData parse5A(byte[] data) {
		return parse59(data);
	}

	/**
	 * AFN=B1H 查询终端固态存储数据
	 * 
	 * @param bytes
	 */
	public static void parseB1(byte[] bytes) throws Exception {

		byte[] type = new byte[1];
		byte[] startTM = new byte[4];
		byte[] endTM = new byte[4];

		System.arraycopy(bytes, 0, type, 0, 1);
		System.arraycopy(bytes, 1, startTM, 0, 4);
		System.arraycopy(bytes, 5, endTM, 0, 4);

		int num = (byte) (type[0] & 0x0F);

		SimpleDateFormat sdftm = new SimpleDateFormat("yyMMddHH");

		ArrayUtils.reverse(startTM);
		String starttime = ByteUtil.bcd2Str(startTM);
		sdftm.parse(starttime);

		ArrayUtils.reverse(endTM);
		String endtime = ByteUtil.bcd2Str(startTM);
		sdftm.parse(endtime);

	}

	/**
	 * AFN=B2H 查询终端内存自报数据
	 * 
	 * @param bytes
	 */
	public static void parseB2(byte[] bytes) throws Exception {

		byte[] startTM = new byte[4];
		byte[] endTM = new byte[4];

		System.arraycopy(bytes, 0, startTM, 0, 4);
		System.arraycopy(bytes, 4, endTM, 0, 4);

		Date curdate = new Date(System.currentTimeMillis());
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy");
		String year = sdf.format(curdate);

		SimpleDateFormat sdftm = new SimpleDateFormat("yyyyMMddHHmm");

		ArrayUtils.reverse(startTM);
		String starttime = year + ByteUtil.bcd2Str(startTM);
		sdftm.parse(starttime);

		ArrayUtils.reverse(endTM);
		String endtime = year + ByteUtil.bcd2Str(startTM);
		sdftm.parse(endtime);

	}

	/**
	 *AFN=5DH 查询遥测终端的事件记录
	 * 
	 * @param bytes
	 */
	public static int[] parse5D(byte[] bytes) {
		int[] erc = new int[32];
		for (int i = 0; i < 32; i++) {
			byte[] dest = new byte[2];
			System.arraycopy(bytes, i * 2, dest, 0, 2);
			erc[i] = ByteUtil.bytesToUshort(dest);
		}
		return erc;
	}

	/**
	 * 解析 遥测终端状态和报警状态（AFN=5EH）命
	 * 
	 * @param bytes
	 */
	public static void parse5E(byte[] bytes) {

		parseAlarm(bytes);
		parseStatus(bytes);
	}

	/**
	 * 解析 水泵电机实时工作数据（AFN=5FH）
	 * 
	 * @param bytes
	 */
	public static void parse5F(byte[] bytes) {

		int len = bytes.length / 2;
		for (int i = 0; i < len; i++) {
			byte[] temp = new byte[2];
			System.arraycopy(bytes, i * 2, temp, 0, 2);
		}
	}

	/**
	 * 查询遥测终端图像记录（AFN=61H）
	 * 
	 * @param bytes
	 */
	public static void parse61(byte[] bytes) {

	}

	public static double[] parse81(byte[] data) {
		System.out.println(">>> 数据种类：流量超限");
		if (data != null) {
			int len = data.length;
			int count = len / 5;
			double[] val = new double[count];
			for (int i = 0; i < count; i++) {// i * 4,(i+1)*4 -1
	
				byte[] temp = new byte[5];
				System.arraycopy(data, i * 5, temp, 0, 5);
				ArrayUtils.reverse(temp);
	
				int flag = 1;
				if ((byte) (temp[0] & 0xf0) == (byte) 0xf0) {
					// 为负值
					flag = -1;
				}
	
				temp[0] = (byte) (temp[0] & 0x0F);
				String value = ByteUtil.bcd2Str(temp);
				String lvalue = value.substring(0, 7);
				String rvalue = value.substring(7, 10);
				String pvalue = lvalue + "." + rvalue;
				val[i] = Double.parseDouble(pvalue) * flag;
				System.out.println(">>> 流量数据：" + val[i]);
	
			}
	
			return val;
		} else {
			return null;
		}
	}

	/**
	 * AFN=90H 复位遥测终端参数和状态命令
	 * 
	 * @param data
	 * @return
	 */
	public static void parse90(byte[] data) {

		// 01H 代表遥测终端复位，重新开始运行，参数不变；
		// 02H 代表遥测终端复位，重新开始运行，遥测终端参数恢复出厂默认值，需要重新配置参数。但是 终端内的历史数据不变。

		if (data[0] == (byte) 0x5A) {
			// 表示终端执行完成！

		}

	}

	/**
	 * 清空遥测终端的历史数据单元（AFN=91H）
	 * 
	 * @param data
	 * @return
	 */
	public static void parse91(byte[] data) {

	}

	/**
	 * AFN=92H 遥控启动水泵或阀门/闸门
	 * 
	 * 
	 *请求帧的数据域:D0～D3 为水泵或阀门/闸门编码号（0～15），D4～D7 为0000(水泵)、1111（阀门/闸门）。
	 * 
	 * D0～D3 为水泵或阀门/闸门编码号（0～15），D4～D7 为1010B 表示执行完毕
	 * 
	 * @param data
	 * @return
	 */
	public static void parse92(byte[] data) {

		int id = (byte) (data[0] & 0x0F);
		byte status = (byte) ((byte) (data[0] & 0xF0) >> 4);

		if (status == (byte) 0xA0) {// 0xA0 == 1010B
			// 执行完成
		}

	}

	/**
	 * AFN=93H 遥控关闭水泵或阀门/闸门
	 * 
	 * @param data
	 * @return
	 */
	public static void parse93(byte[] data) {
		parse92(data);
	}

	/**
	 * AFN=94H 遥控终端或中继站通信机切换
	 * 
	 * 数据域的数据D0～D3 为遥控终端或中继通信机号。
	 * 
	 * D0～D3 为1001B 指通信机A 机为值班机， 0110B 指通信机B 机为值班机，
	 * 
	 * D4～D7 为1010B 表示执行完毕。
	 * 
	 * @param data
	 * @return
	 */
	public static void parse94(byte[] data) {
		byte machine = (byte) (data[0] & 0x0F);
		byte status = (byte) ((byte) (data[0] & 0xF0) >> 4);

		if (machine == (byte) 0x09) {// 表示为 1001B 指通信机A

		}

		if (machine == (byte) 0x06) {// 0110B 指通信机B 机为值班机，

		}

		if (status == (byte) 0xA0) {// 0xA0 == 1010B
			// 执行完成
		}

	}

	/**
	 * AFN=95H 遥控中继站工作机切换
	 * 
	 * @param data
	 * @return
	 */
	public static void parse95(byte[] data) {
		parse94(data);
	}

	/**
	 * 解析 密钥和密码的计算值
	 * 
	 * @param data
	 * @return
	 */
	public static void parse96(byte[] data) {

	}

	/**
	 * 解析数据
	 * 
	 * @param control
	 *            控制位
	 * @param afn
	 *            功能码
	 * @param data
	 *            数据
	 */
	public static IData parseData(byte control, byte afn, byte[] data) {
		int[] ctrl = parseControl(control);
		// int[] ctrl = parseControl(body.getControl());
		// String stcd = parseAddress(body.getAddress());
		// byte[] data = body.getUserData().getContent();
		System.out.println("==================" + SzyConst.AFN.get(afn)
				+ "=======================");

		DataC0 c0 = new DataC0();
		c0.setType(ctrl[3]);

		double[] d = null;

		switch (ctrl[3]) {
		case 1: // 查询雨量参数
			double p = parseC0D1(data, true);
			d = new double[] { p };
			break;
		case 2:// 查询水位参数
			d = parseC0D2(data);
			break;
		case 3:// 查询流量（水量）参数
			if (afn == (byte) 0x81) {
				d = parse81(data);
			} else {
				d = parseC0D3(data);
			}
			break;
		case 4:// 查询流速参数
			d = parseC0D4(data);
			break;
		case 5:
			d = parseC0D5(data);
			break;
		case 6:
			d = parseC0D6(data);
			break;
		case 7:
			d = parseC0D7(data);
			break;
		case 8:
			d = parseC0D8(data);
			break;
		case 9:
			d = parseC0D9(data);
			break;
		case 10:
			// parseD10(data);
			break;
		case 11:
			d = parseC0D11(data);
			break;
		case 12:
			d = parseC0D12(data);
			break;
		case 13:
			d = parseC0D13(data);
			break;
		case 14:
			// parseD14(data);
			break;
		case 15:

			break;
		}

		c0.setData(d);

		return c0;
	}

	/**
	 * 解析遥测站终端状态
	 * 
	 * 1) D0，D1—终端的工作模式。00H，终端在自报、遥测工作状态；01H，终端在自报确认工作 //
	 * 状态；02H，—终端在遥测工作状态；03H，终端在调试或维修状态。 2) D2—终端IC 卡功能是否有效。0：无效；1：有效。
	 * 
	 * 3) D3—定值控制是否投入。0：退出；1：投入。
	 * 
	 * 4) D4—水泵工作状态。 0：启动；1：停止。
	 * 
	 * 5) D5—终端箱门状态。0：开启；1：关闭。
	 * 
	 * 6) D6—电源工作状态。0：AC220V 供电；1：蓄电池供电。
	 * 
	 * @param bytes
	 *            终端状态数据
	 */
	public static void parseStatus(byte[] bytes) {

		String sstr = ByteUtil.toBinaryString(bytes);

		String astr1 = sstr.substring(0, 8);
		String astr2 = sstr.substring(8, 16);
		sstr = StringUtils.reverse(astr1) + StringUtils.reverse(astr2);

		String D01 = sstr.substring(0, 2);
		String D2 = sstr.substring(2, 3);
		String D3 = sstr.substring(3, 4);
		String D4 = sstr.substring(4, 5);
		String D5 = sstr.substring(5, 6);
		String D6 = sstr.substring(6, 7);
		System.out.println("==============遥测站终端状态"
				+ ByteUtil.toHexString(bytes) + "=======================");
		System.out
				.println(" D0，D1—终端的工作模式  \t\t"
						+ D01
						+ " "
						+ (D01.equals("00") ? "终端在自报、遥测工作状态！" : (D01
								.equals("01") ? "终端在自报确认工作状态！" : (D01
								.equals("10") ? "终端在遥测工作状态！" : "终端在调试或维修状态！"))));
		System.out.println(" D2—终端IC 卡功能是否有效  \t" + D2 + " "
				+ (D2.equals("0") ? "无效！" : "有效！"));
		System.out.println(" D3—定值控制是否投入  \t\t" + D3 + " "
				+ (D3.equals("0") ? "退出！" : "投入！"));
		System.out.println(" D4—水泵工作状态  \t\t" + D4 + " "
				+ (D4.equals("0") ? "启动！" : "停止！"));
		System.out.println(" D5—终端箱门状态  \t\t" + D5 + " "
				+ (D5.equals("0") ? "开启！" : "关闭！"));
		System.out.println(" D6—电源工作状态  \t\t" + D6 + " "
				+ (D6.equals("0") ? "AC220V 供电！" : "蓄电池供电！"));

	}

	/**
	 * 解析遥测站报警状态
	 * 
	 * 1) D0—工作交流电停电告警； 2) D1—蓄电池电压报警；
	 * 
	 * 3) D2—水位超限报警； 4) D3—流量超限报警；
	 * 
	 * 5) D4—水质超限报警； 6) D5—流量仪表故障报警；
	 * 
	 * 7) D6—水泵开停状态； 8) D7—水位仪表故障报警；
	 * 
	 * 9) D8—水压超限报警； 10) D9—备用；
	 * 
	 * 11) D10—终端IC 卡功能报警； 12) D11—定值控制报警；
	 * 
	 * 13) D12—剩余水量的下限报警 14) D13—终端箱门状态报警；
	 * 
	 * @param bytes
	 *            报警状态数据
	 */
	public static void parseAlarm(byte[] bytes) {
		if (bytes != null) {
			// ArrayUtils.reverse(bytes);
			String astr = ByteUtil.toBinaryString(bytes);
			// 需要采用8位反转的方法
			System.out.println("==================遥测站报警状态  " + astr
					+ "=======================");

			String astr1 = astr.substring(0, 8);
			String astr2 = astr.substring(8, 16);
			astr = StringUtils.reverse(astr1) + StringUtils.reverse(astr2);

			for (int i = 0, len = astr.length(); i < len; i++) {
				String s = astr.substring(i, i + 1);
				System.out.println(" "
						+ StringUtils.rightPad(SzyConst.ALARM[i], 60, " ")
						+ "\t" + s + " " + (s.equals("0") ? "(正常！)" : "(报警！)"));
			}

		}

	}

	/**
	 * 雨量参数：雨量值3 字节，取值范围为0～99999.9，单位为mm，数据域3＋4 字节。
	 * 
	 * 如果采用的雨量仪表是翻斗式雨量计，则取值范围为0～999999（循环计数累计值），单位为每斗的分辨率。
	 * 
	 * @param data
	 * @return
	 */
	public static double parseC0D1(byte[] data, boolean type) {

		ArrayUtils.reverse(data);
		String value = ByteUtil.bcd2Str(data);

		if (type) {
			// 翻斗式雨量计
			String lvalue = value.substring(0, 5);
			String rvalue = value.substring(5, 6);
			String pvalue = lvalue + "." + rvalue;
			return Double.parseDouble(pvalue);
		} else {
			return Double.parseDouble(value);
		}

	}

	/**
	 * 查询水位参数：水位仪表数量有N 个，每个水位值4 字节，取值范围为-9999.999～+9999.999，单位为m
	 * 
	 * @param data
	 * @return
	 */
	public static double[] parseC0D2(byte[] data) {
		if (data != null) {
			int len = data.length;
			int count = len / 4;
			double[] val = new double[count];
			for (int i = 0; i < count; i++) {// i * 4,(i+1)*4 -1

				byte[] temp = new byte[4];
				System.arraycopy(data, i * 4, temp, 0, 4);
				ArrayUtils.reverse(temp);

				int flag = 1;
				if ((byte) (temp[0] & 0xf0) == (byte) 0xf0) {
					// 为负值
					flag = -1;
				}

				temp[0] = (byte) (temp[0] & 0x0F);
				String value = ByteUtil.bcd2Str(temp);
				String lvalue = value.substring(0, 5);
				String rvalue = value.substring(5, 8);
				String pvalue = lvalue + "." + rvalue;
				val[i] = Double.parseDouble(pvalue) * flag;
			}
			return val;
		} else {
			return null;
		}
	}

	/**
	 * 查询流量（水量）参数：流量（水量）仪表数量为N。每个流量数据为5
	 * 个字节压缩BCD。取值范围为-999999.999～+999999.999，单位为m3/s，m3/h（水资源）。
	 * 
	 * 水量为累计取水量， 5个字节为压缩BCD 码，取值范围为0～7999999999，单位为m3，
	 * 
	 * BYTE 5 的D7 位为累计水量的符号位： 0 为正值； 1 为负值。
	 * 
	 * @param data
	 * @return
	 */
	public static double[] parseC0D3(byte[] data) {
		System.out.println(">>> 数据种类：流量（水量）参数");
		if (data != null) {
			int len = data.length;
			int count = len / 5;
			double[] val = new double[count];
			for (int i = 0; i < count; i++) {// i * 4,(i+1)*4 -1

				byte[] temp = new byte[5];
				System.arraycopy(data, i * 5, temp, 0, 5);
				ArrayUtils.reverse(temp);

				if (i == (count - 1)) {
					int flag = (byte) (temp[0] & 0x80) >> 7;
					if (flag == 1) {
						flag = -1;
					} else {
						flag = 1;
					}
					temp[0] = (byte) (temp[0] & 0x7F);
					String value = ByteUtil.bcd2Str(temp);
					val[i] = Double.parseDouble(value) * flag;
					System.out.println(">>> 累计水量：" + val[i]);
				} else {
					int flag = 1;
					if ((byte) (temp[0] & 0xf0) == (byte) 0xf0) {
						// 为负值
						flag = -1;
					}

					temp[0] = (byte) (temp[0] & 0x0F);
					String value = ByteUtil.bcd2Str(temp);
					String lvalue = value.substring(0, 7);
					String rvalue = value.substring(7, 10);
					String pvalue = lvalue + "." + rvalue;
					val[i] = Double.parseDouble(pvalue) * flag;
					System.out.println(">>> 流量数据：" + val[i]);
				}
			}

			return val;
		} else {
			return null;
		}
	}

	/**
	 * 查询流速参数：流速仪表数量为N。每个流速数据为3 个字节压缩BCD。
	 * 
	 * 取值范围为-99.999～+99.999，单位为m/s。数据域3*N＋4 字节。
	 * 
	 * @param data
	 * @return
	 */
	public static double[] parseC0D4(byte[] data) {
		if (data != null) {
			int len = data.length;
			int count = len / 3;
			double[] val = new double[count];
			for (int i = 0; i < count; i++) {// i * 4,(i+1)*4 -1

				byte[] temp = new byte[3];
				System.arraycopy(data, i * 3, temp, 0, 3);
				ArrayUtils.reverse(temp);

				int flag = (byte) (temp[0] & 0xf0) >> 4;
				if (flag == 0) {
					flag = 1;
				} else {
					flag = -1;
				}

				temp[0] = (byte) (temp[0] & 0x0F);
				String value = ByteUtil.bcd2Str(temp);
				String lvalue = value.substring(0, 3);
				String rvalue = value.substring(3, 6);
				String pvalue = lvalue + "." + rvalue;
				val[i] = Double.parseDouble(pvalue) * flag;

			}
			return val;
		} else {
			return null;
		}
	}

	/**
	 * 查询闸位参数：闸位仪表数量有N 个，每个闸位值3 字节
	 * 
	 * 取值范围为0～999.99，单位为m，数据域3*N＋4 字节。
	 * 
	 * @param data
	 * @return
	 */
	public static double[] parseC0D5(byte[] data) {
		int len = data.length;
		int count = len / 3;
		double[] val = new double[count];
		for (int i = 0; i < count; i++) {

			byte[] temp = new byte[3];
			System.arraycopy(data, i * 3, temp, 0, 3);
			ArrayUtils.reverse(temp);

			String value = ByteUtil.bcd2Str(temp);
			String lvalue = value.substring(0, 4);
			String rvalue = value.substring(4, 6);
			String pvalue = lvalue + "." + rvalue;
			val[i] = Double.parseDouble(pvalue);
		}
		return val;
	}

	/**
	 * 查询功率参数：功率仪表数量为N。每个功率数据为3 个字节压缩BCD。
	 * 
	 * 取值范围为0～999999， 单位为kw。数据域3*N＋4 字节。
	 * 
	 * @param data
	 * @return
	 */
	public static double[] parseC0D6(byte[] data) {
		int len = data.length;
		int count = len / 3;
		double[] val = new double[count];
		for (int i = 0; i < count; i++) {

			byte[] temp = new byte[3];
			System.arraycopy(data, i * 3, temp, 0, 3);
			ArrayUtils.reverse(temp);

			String value = ByteUtil.bcd2Str(data);
			val[i] = Double.parseDouble(value);
		}
		return val;
	}

	/**
	 * 查询气压参数：气压数据为3 个字节压缩BCD。
	 * 
	 * 取值范围为0～99999，单位为102pa。数据域 3＋4 字节。
	 * 
	 * @param data
	 * @return
	 */
	public static double[] parseC0D7(byte[] data) {
		return parseC0D6(data);
	}

	/**
	 * 查询风速（含风向）参数：风速数据为3 个字节压缩BCD。
	 * 
	 * 取值范围为0～999.99，单位为m/s。 风向为1 位BCD，取值0～8。数据域4＋4字节。
	 * 
	 * @param data
	 * @return
	 */
	public static double[] parseC0D8(byte[] data) {
		int len = data.length;
		int count = len / 3;
		double[] val = new double[count];
		for (int i = 0; i < count; i++) {

			byte[] temp = new byte[3];
			System.arraycopy(data, i * 3, temp, 0, 3);
			ArrayUtils.reverse(temp);

			byte dir = (byte) ((temp[0] & 0xF0) >> 4);

			temp[0] = (byte) (temp[0] & 0x0F);
			String value = ByteUtil.bcd2Str(temp);
			String lvalue = value.substring(0, 4);
			String rvalue = value.substring(4, 6);
			String pvalue = lvalue + "." + rvalue;
			val[i] = Double.parseDouble(pvalue);
		}
		return val;
	}

	/**
	 * 查询水温参数：水温数据为2 个字节压缩BCD。
	 * 
	 * 取值范围为0～99.9，单位为℃。数据域2＋4 字节
	 * 
	 * @param data
	 * @return
	 */
	public static double[] parseC0D9(byte[] data) {
		int len = data.length;
		int count = len / 2;
		double[] val = new double[count];
		for (int i = 0; i < count; i++) {

			byte[] temp = new byte[2];
			System.arraycopy(data, i * 2, temp, 0, 2);

			String value = ByteUtil.bcd2Str(data);
			String lvalue = value.substring(0, 3);
			String rvalue = value.substring(3, 4);
			String pvalue = lvalue + "." + rvalue;
			val[i] = Double.parseDouble(pvalue);
		}
		return val;
	}

	/**
	 * 查询土壤含水率参数：土壤含水率仪表数量为N。每个土壤含水率数据为2 个字节压缩BCD。
	 * 
	 * 取值范围为0～999.9，无单位。数据域2*N＋4 字节。
	 * 
	 * @param data
	 * @return
	 */
	public static double[] parseC0D11(byte[] data) {
		return parseC0D9(data);
	}

	/**
	 * 查询蒸发量参数：蒸发量数据为3 个字节压缩BCD。
	 * 
	 * 取值范围为0～9999.9，单位为mm。数据域3*N＋4 字节。
	 * 
	 * @param data
	 * @return
	 */
	public static double[] parseC0D12(byte[] data) {
		int len = data.length;
		int count = len / 3;
		double[] val = new double[count];
		for (int i = 0; i < count; i++) {

			byte[] temp = new byte[3];
			System.arraycopy(data, i * 3, temp, 0, 3);
			ArrayUtils.reverse(temp);

			String value = ByteUtil.bcd2Str(temp);
			String lvalue = value.substring(0, 5);
			String rvalue = value.substring(5, 6);
			String pvalue = lvalue + "." + rvalue;
			val[i] = Double.parseDouble(pvalue);
		}
		return val;
	}

	/**
	 * 查询水压参数：水压仪表数量为N 个，每个水压数据为4 个字节的BCD，低位在前，高位在后，
	 * 
	 * 取值范围为0～999999.99，单位为kPa。数据域4*N＋4 字节。数
	 * 
	 * @param data
	 * @return
	 */
	public static double[] parseC0D13(byte[] data) {
		System.out.println(">>> 数据种类：查询水压参数");
		int len = data.length;
		int count = len / 4;
		double[] val = new double[count];
		for (int i = 0; i < count; i++) {

			byte[] temp = new byte[4];
			System.arraycopy(data, i * 4, temp, 0, 4);
			ArrayUtils.reverse(temp);

			String value = ByteUtil.bcd2Str(temp);
			String lvalue = value.substring(0, 6);
			String rvalue = value.substring(6, 8);
			String pvalue = lvalue + "." + rvalue;
			val[i] = Double.parseDouble(pvalue);
		}
		return val;
	}

	// public static double[] parseC0(byte[] data) {
	//		
	// }

	private byte[] convert7F(byte[] data) {
		ArrayUtils.reverse(data);
		int flag = (byte) (data[0] & 0x80) >> 7;
		if (flag == 1) {
			flag = -1;
		} else {
			flag = 1;
		}
		data[0] = (byte) (data[0] & 0x7F);
		return data;
	}

	private static double convertDecimal(byte[] data, int length, int pos) {
		String value = ByteUtil.bcd2Str(data);
		String lvalue = value.substring(0, pos);
		String rvalue = value.substring(pos, length);
		String pvalue = lvalue + "." + rvalue;
		return Double.parseDouble(pvalue);
	}

	public static void main(String[] args) throws IOException {
		String hexString = "";

		int pos = 0;

		byte control = 0x14;
		int[] C = SzyParser.parseControl(control);
		System.out.println(">> 控制域：" + (C[0] == 1 ? "上行" : "下行") + "_" + C[0]
				+ " \t" + (C[1] == 0 ? "单帧" : "多帧") + "_" + C[1] + " \t"
				+ " 传输" + "_" + C[2] + "\t" + SzyConst.FUNC[C[3]]);
		
		hexString = "681A68B3420101392BC0000000040059269603000800200000001605006016";
		// [累计水量:3962659] [流量:4000]

		hexString = "681A68B3420701FA2AC0000000000030502901000800200000000429002D16";
		// // [累计水量:8] [流量:0]//
		
		hexString = "681368B13201010001C00000000100530037401122004F16";

		byte[] bytes = ByteUtil.HexStringToBinary(hexString);

		parseMessage(bytes);

		// SzyMessageBody msgBody = new SzyMessageBody();
		// msgBody.setControl(control);
		// msgBody.setAddress(address);
		// msgBody.setUserData(userdata);
		System.out.println("==============     OK      ======================="
				+ ByteUtil.toBinaryString((byte) 0xA0));

		String stcd = "420701011002";
		byte[] stcdbytes = SzyBuilder.newStcd(stcd);
		String s2 = SzyParser.parseStcd(stcdbytes);

		System.out.println("==============  stcd  ==============" + s2);

		byte c = SzyBuilder.newControl(0, 0, 3, 12);
		parseControl(c);

		byte[] pwd = SzyBuilder.newPW(1, 234);
		String[] pwdstr = SzyParser.parsePW(pwd);
		System.out.println("==pwdstr[0]=" + pwdstr[0] + "==pwdstr[1]=" + pwdstr[1]);

		String s57 = "00592696030008002000002000";
		IData d57 = parse57(ByteUtil.HexStringToBinary(s57));
		// System.out.println("==============  d57  ==============" +
		// d57.length);

		//
		// String value = "003456";
		// String lvalue = value.substring(0, 5);
		// String rvalue = value.substring(5, 6);
		// String pvalue = lvalue + "." + rvalue;
		//
		// System.out.println("--------------" + Double.parseDouble(pvalue)
		// + "--------------");

	}
}
